package top.ochiamalu.aioj.strategy.judge.impl;

import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import top.ochiamalu.aioj.domain.bo.ExecuteMessage;
import top.ochiamalu.aioj.domain.entity.TestCase;
import top.ochiamalu.aioj.factory.CodeExecutorFactory;
import top.ochiamalu.aioj.strategy.judge.CodeExecutor;
import top.ochiamalu.aioj.util.ProcessUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static top.ochiamalu.aioj.constant.JudgeConstants.GLOBAL_CODE_DIR_NAME;
import static top.ochiamalu.aioj.constant.JudgeConstants.MAX_COMPILER_OUTPUT_LENGTH;

/**
 * Python代码执行器
 *
 * @author ochiamalu
 * @date 2025/06/20
 */
@Slf4j
@Component
public class PythonCodeExecutor implements CodeExecutor {

    private static final String PYTHON_SCRIPT_NAME = "main.py";

    @Resource
    private CodeExecutorFactory codeExecutorFactory;

    @PostConstruct
    public void init() {
        codeExecutorFactory.register("python", this);
    }

    @Override
    public File saveCodeToFile(String code) {
        String userDir = System.getProperty("user.dir");
        String globalCodePathName = userDir + File.separator + GLOBAL_CODE_DIR_NAME;
        // 判断全局代码目录是否存在，没有则新建
        if (!FileUtil.exist(globalCodePathName)) {
            FileUtil.mkdir(globalCodePathName);
        }

        // 把用户的代码隔离存放
        String userCodeParentPath = globalCodePathName + File.separator + UUID.randomUUID();
        String userCodePath = userCodeParentPath + File.separator + PYTHON_SCRIPT_NAME;
        return FileUtil.writeString(code, userCodePath, StandardCharsets.UTF_8);
    }

    @Override
    public ExecuteMessage compileFile(File userCodeFile) {
        // Python是解释型语言，不需要编译步骤
        ExecuteMessage executeMessage = new ExecuteMessage();
        executeMessage.setExitValue(0);
        executeMessage.setMessage("Python不需要编译");
        return executeMessage;
    }

    @Override
    public List<ExecuteMessage> runFile(File userCodeFile, List<TestCase> testCaseList) {
        List<ExecuteMessage> executeMessageList = new ArrayList<>();
        for (TestCase testCase : testCaseList) {
            String runCmd = buildRunCommand(userCodeFile.getAbsolutePath());
            String[] cmd = runCmd.split(" ");
            try {
                ProcessBuilder processBuilder = new ProcessBuilder(cmd);
                processBuilder.redirectErrorStream(true);
                Process process = processBuilder.start();

                ExecuteMessage executeMessage = ProcessUtils.runProgram(process, testCase);

                executeMessage.setTestCaseId(testCase.getId());
                executeMessage.setHint(testCase.getHint());
                executeMessage.setScore(testCase.getScore());

                executeMessageList.add(executeMessage);
            } catch (Exception e) {
                throw new RuntimeException("执行错误", e);
            }
        }
        return executeMessageList;
    }

    @Override
    public boolean deleteFile(File userCodeFile) {
        if (userCodeFile.getParentFile() != null) {
            String userCodeParentPath = userCodeFile.getParentFile().getAbsolutePath();
            return FileUtil.del(userCodeParentPath);
        }
        return true;
    }

    @Override
    public String handleErrorMessage(File userCodeFile, String errorMessage) {
        String absolutePath = userCodeFile.getAbsolutePath();
        return errorMessage.replace(absolutePath, PYTHON_SCRIPT_NAME)
                .substring(0, Math.min(errorMessage.length(), MAX_COMPILER_OUTPUT_LENGTH));
    }

    @Override
    public String getCompilerName() {
        return "Python(python)";
    }

    /**
     * 构建运行命令
     *
     * @param scriptPath Python脚本路径
     * @return 运行命令
     */
    private String buildRunCommand(String scriptPath) {
        return String.format("python %s", scriptPath);
    }
} 